package com.feidee.data.report.util.quartz;

import com.feidee.data.report.util.DbOperationUtil;
import com.feidee.fdcommon.configuration.CustomConfiguration;
import com.feidee.fdfalcon.falcon.FalconAlarmService;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.Calendar;

/**
 * @author CHQ
 * @date 2019-11-20
 * @description 监控门户自定义报表每天凌晨0-8点执行的报表，每一时刻发现有执行失败的报表或未达到报表执行成功的阈值情况，
 * 立马发送预警短信通知！
 */
@Component
public class FindExecuteStatusReport {
    private static Logger logger = LoggerFactory.getLogger(FindExecuteStatusReport.class);
    private DataSource confDataSource;
    private DataSource cusMysqlDataSource;

    public void runStatusQuery() {
        sendMsgIfLessMinValue();
    }

    public void sendMsgIfLessMinValue() {
        Connection conn = null;
        Connection confConn = null;
        PreparedStatement statement = null;
        PreparedStatement confstatement = null;
        ResultSet rs = null;
        ResultSet confRs = null;
        Calendar calendar;
        String executeSuccessCount = "";
        String msgThresholdConfKey = "";
        String dsSyncThresholdKey = "";
        String msgContent = "";
        String syncSuccessCount = "";
        String findZeroTimeSuccessfulReportCountSqlStr;
        int curHour;
        int thresholdConfInt;
        int dsSyncThreshold;

        try {
            //获取当前时刻
            calendar = Calendar.getInstance();
            curHour = calendar.get(Calendar.HOUR_OF_DAY);

            //获取0时到当前时刻执行成功的报表数量
            findZeroTimeSuccessfulReportCountSqlStr = "select count(report_key) as execute_success_count " +
                    "from report_monitor_result where substring(update_time,1,10)=CURRENT_DATE " +
                    "and substring(update_time,-8) between '00:00:00' and '0" + (curHour - 1) +
                    ":59:59' and exec_status in('ZXCG') and report_key is not null";
            logger.info("凌晨预警 查询执行成功的报表数量sql为：" + findZeroTimeSuccessfulReportCountSqlStr);
            conn = cusMysqlDataSource.getConnection();
            statement = conn.prepareStatement(findZeroTimeSuccessfulReportCountSqlStr);
            rs = statement.executeQuery();
            while (rs.next()) {
                executeSuccessCount = rs.getString("execute_success_count");
            }

            //获取当前时刻理论上应该执行成功的报表数量和数据源同步成功阈值
            switch (curHour) {
                case 1:
                    msgThresholdConfKey = "one.min.success.count";
                    dsSyncThresholdKey = "one.clock.ds.sync.success.count";
                    break;
                case 2:
                    msgThresholdConfKey = "two.min.success.count";
                    dsSyncThresholdKey = "two.clock.ds.sync.success.count";
                    break;
                case 3:
                    msgThresholdConfKey = "three.min.success.count";
                    dsSyncThresholdKey = "three.clock.ds.sync.success.count";
                    break;
                case 4:
                    msgThresholdConfKey = "four.min.success.count";
                    dsSyncThresholdKey = "four.clock.ds.sync.success.count";
                    break;
                case 5:
                    msgThresholdConfKey = "five.min.success.count";
                    dsSyncThresholdKey = "five.clock.ds.sync.success.count";
                    break;
                case 6:
                    msgThresholdConfKey = "six.min.success.count";
                    dsSyncThresholdKey = "six.clock.ds.sync.success.count";
                    break;
                case 7:
                    msgThresholdConfKey = "seven.min.success.count";
                    dsSyncThresholdKey = "seven.clock.ds.sync.success.count";
                    break;
                case 8:
                    msgThresholdConfKey = "eight.min.success.count";
                    dsSyncThresholdKey = "eight.clock.ds.sync.success.count";
                    break;
                default:
            }

            //如果当前时刻执行成功的报表数量小于设定阈值，则构造预警短信
            thresholdConfInt = CustomConfiguration.getInt(msgThresholdConfKey);
            if (Integer.parseInt(executeSuccessCount) < thresholdConfInt) {
                msgContent = constrctMessageContent(curHour, executeSuccessCount, thresholdConfInt);

                //获取0时到当前时刻数据源同步成功的个数 2020-07-27
                String DsSyncSuccessCountSqlStr = "select count(meta_key) as sync_success_count " +
                        "from report_metadata_status where substring(update_time,1,10)=CURRENT_DATE " +
                        "and substring(update_time,-8) between '00:00:00' and '0" + (curHour - 1) +
                        ":59:59' and meta_status in('SUCCESS') and meta_key is not null";
                logger.info("凌晨预警 查询当前时间数据源同步个数sql为：" + DsSyncSuccessCountSqlStr);
                confConn = confDataSource.getConnection();
                confstatement = confConn.prepareStatement(DsSyncSuccessCountSqlStr);
                confRs = confstatement.executeQuery();
                while (confRs.next()) {
                    syncSuccessCount = confRs.getString("sync_success_count");
                }

                //新增数据源同步情况预警内容 2020-07-27
                dsSyncThreshold = CustomConfiguration.getInt(dsSyncThresholdKey);
                msgContent += "当前数据源同步情况：理论上大概需要同步" + dsSyncThreshold +
                        "张源表，实际同步" + syncSuccessCount + "张(若实际>理论，请忽略)";
            } else {
                logger.info("凌晨预警 当前时刻：" + curHour + " 执行报表成功数量: " + executeSuccessCount + "无需发送告警!");
            }

            //当构造的短信内容不为空，则触发短信预警
            if (StringUtils.isNotBlank(msgContent)) {
                logger.info("凌晨预警 短信内容：" + msgContent);
                FalconAlarmService.sendAlarm(msgContent, "data.pm.alarm", "datafeidee",
                        CustomConfiguration.getString("message.pwd"));
            }

            logger.info("凌晨预警 查询数据库正常结束！");
        } catch (Exception e) {
            logger.error("凌晨预警 查询数据库异常：", e);
        } finally {
            DbOperationUtil.cleanConnEnv(conn, statement, rs);
            DbOperationUtil.cleanConnEnv(confConn, confstatement, confRs);
        }
    }

    /**
     * @param hour  0-8时某一时刻
     * @param count 0-8时某一时刻执行成功的报表数量
     * @param min   0-8时某一时刻应该达到的执行成功的报表数量的阈值
     * @description 构造短信内容
     */
    private String constrctMessageContent(int hour, String count, int min) {
        return hour + "时执行报表数量为" + count + "张，小于设定阈值" + min + "张，请关注！";
    }

    public void setConfDataSource(DataSource confDataSource) {
        this.confDataSource = confDataSource;
    }

    public DataSource getConfDataSource() {
        return confDataSource;
    }

    public void setCusMysqlDataSource(DataSource cusMysqlDataSource) {
        this.cusMysqlDataSource = cusMysqlDataSource;
    }

    public DataSource getCusMysqlDataSource() {
        return cusMysqlDataSource;
    }
}
